package com.yc.mypredictefactory;

import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

/**
 * 基于地理位置的网关路由断言工厂
 * 根据客户端IP地址判断是否允许访问特定路由
 */
@Slf4j
@Component
public class IpRegionRoutePredicateFactory extends AbstractRoutePredicateFactory<IpRegionRoutePredicateFactory.Config> {

    // IP地址查询器
    private final Searcher searcher;

    /**
     * 构造函数
     * @param searcher IP地址查询器实例
     */
    public IpRegionRoutePredicateFactory(Searcher searcher) {
        super(Config.class);
        this.searcher = searcher;
    }

    /**
     * 创建路由断言
     * @param config 配置对象
     * @return 返回一个判断请求是否允许通过的断言
     */
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            // 获取客户端IP
            String clientIp = getClientIp(exchange);
            log.info(" Client IP: " + clientIp);
            try {
                // 查询IP所在地区
                String region = searcher.search(clientIp);
                log.info(" Region: " + region);
                // 提取国家（region格式为"国家|地区|省份|城市|运营商"）
                String country = region != null ? region.split("\\|")[0] : "Unknown";

                log.info(" Country: " + country);
                // 检查国家是否在允许列表中
                boolean isAllowed = config.getAllowedCountries().contains(country);
                log.info(" Allowed: " + isAllowed);
                return isAllowed;
            } catch (Exception e) {
                log.error(" IP 解析失败: " + clientIp + ", Error: " + e.getMessage());
                return false;
            }
        };
    }

    /**
     * 获取客户端真实IP地址
     * @param exchange 服务器Web交换对象
     * @return 客户端IP地址
     */
    private String getClientIp(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        // 尝试从X-Forwarded-For头部获取IP
        String ip = request.getHeaders().getFirst("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeaders().getFirst("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeaders().getFirst("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            // 从请求连接中获取IP
            ip = request.getRemoteAddress().getAddress().getHostAddress();
        }
        return ip;
    }

    /**
     * 配置类，用于存储允许访问的国家列表
     */
    public static class Config {
        // 允许访问的国家代码列表
        private List<String> allowedCountries;

        public List<String> getAllowedCountries() {
            return allowedCountries;
        }

        public void setAllowedCountries(List<String> allowedCountries) {
            this.allowedCountries = allowedCountries;
        }
    }

    /**
     * 获取配置属性的快捷字段顺序
     * @return 配置属性名称列表
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("allowedCountries");
    }
}